package cn.lili.modules.order.order.serviceimpl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.digest.MD5;
import cn.lili.cache.LockPrefix;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.ApiProperties;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.PayWayEnum;
import cn.lili.common.security.enums.VipStatusEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.ResultUtil;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.client.UserClient;
import cn.lili.modules.member.client.VipClient;
import cn.lili.modules.member.entity.dos.User;
import cn.lili.modules.order.order.entity.constant.OrderConstant;
import cn.lili.modules.order.order.entity.dos.PrizeGoods;
import cn.lili.modules.order.order.entity.dos.PrizeOrder;
import cn.lili.modules.order.order.entity.dto.PrizeOrderDTO;
import cn.lili.modules.order.order.entity.vo.PrizeOrderStatisticsVO;
import cn.lili.modules.order.order.entity.vo.ViewLogisticVO;
import cn.lili.modules.order.order.mapper.PrizeOrderMapper;
import cn.lili.modules.order.order.service.PrizeGoodsService;
import cn.lili.modules.order.order.service.PrizeOrderService;
import cn.lili.modules.system.client.DictionaryClient;
import cn.lili.modules.system.client.LogisticsClient;
import cn.lili.modules.system.constants.DictConstant;
import cn.lili.modules.system.entity.dos.Dictionary;
import cn.lili.modules.system.entity.dos.LiVip;
import cn.lili.modules.system.entity.vo.Traces;
import cn.lili.mybatis.util.PageUtil;
import com.alibaba.fastjson.JSONObject;
import com.api.PayApi;
import com.api.UserApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pojos.UserRes;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author asus
 * @description 针对表【li_prize_order(中奖记录表)】的数据库操作Service实现
 * @createDate 2024-01-18 13:45:59
 */
@RequiredArgsConstructor(onConstructor_ = @Lazy)
@Service
@Slf4j
public class PrizeOrderServiceImpl extends ServiceImpl<PrizeOrderMapper, PrizeOrder>
        implements PrizeOrderService {

    private final LogisticsClient logisticsClient;

    private final PrizeGoodsService prizeGoodsService;

    private final DictionaryClient dictionaryClient;

    private final PayApi payApi;

    private final UserApi userApi;

    private final UserClient userClient;

    private final VipClient vipClient;

    @Value("${fw.appid}")
    String appId;

    @Value("${fw.secrect}")
    String secret;

    private final ApiProperties apiProperties;

    private final RedissonClient redisson;

    /**
     * 抽奖
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage<Object> prizeDraw(String freePayKey) {
        log.info("freePayKey == {}", freePayKey);
        if (StringUtils.isEmpty(freePayKey)) {
            throw new ServiceException("freePayKey为空");
        }

        Dictionary dictionary = dictionaryClient.getDict(Dictionary.builder().code(DictConstant.PRIZE_PRICE_NO).value(DictConstant.PRIZE_PRICE_01 + "").build());
        if (dictionary == null || StringUtils.isEmpty(dictionary.getId())) {
            throw new ServiceException("未获取到，抽奖所需f分，请联系管理员配置");
        }
        // 获取用户绿色积分余额
        UserRes userRes = payApi.getUserMoney(UserContext.getCurrentUser().getOpenId());
        if (new BigDecimal(userRes.getBalance()).compareTo(BigDecimal.valueOf(Double.parseDouble(dictionary.getValueName()))) <= 0) {
            throw new ServiceException("f分不足");
        }

        RLock lock = null;
        //锁后进行抽奖
        try {
            lock = redisson.getLock(LockPrefix.CALLBACK_PRIZE.getPrefix() + freePayKey);
            lock.lock(100, TimeUnit.SECONDS);
            //获取可参与抽奖的商品
            List<PrizeGoods> prizeGoodsList = this.prizeGoodsList();
            if (CollectionUtil.isEmpty(prizeGoodsList)) {
                throw new ServiceException("请先配置，抽奖奖品");
            }
            //抽奖
            PrizeGoods result = this.getLotteryItem(prizeGoodsList);
            AuthUser currentUser = UserContext.getCurrentUser();
            if (currentUser == null) {
                throw new ServiceException("登录已过期");
            }
            String sn = SnowFlake.createStr("P");
            //创建订单
            PrizeOrder prizeOrder = PrizeOrder.builder()
                    .userId(currentUser.getId())
                    .memberName(currentUser.getUsername())
                    .nickName(currentUser.getNickName())
                    .price(BigDecimal.valueOf(Double.parseDouble(dictionary.getValueName())))
                    .prizeId(result.getId())
                    .prizeName(result.getGoodsName())
                    .prizeImg(result.getGoodsImage())
                    .prizeType(result.getGoodsType())
                    .prizeStatus(1)
                    .isNeedToCollect(result.getIsNeedToCollect())
                    .sn(sn)
                    .build();
            //免密支付
            if (StringUtils.isNotEmpty(freePayKey)) {
                //扣除f分
                boolean isDeductMoney = true;
                String msg = "";
                try {
                    JSONObject obj = payApi.freePay(2, 5, "抽奖F分抵扣"
                            , new BigInteger(String.valueOf(CurrencyUtil.mul(Double.parseDouble(dictionary.getValueName()), 100).longValue())),
                            sn, freePayKey, new BigInteger("0"));
                    System.out.println(obj);
                } catch (Exception e) {
                    log.error("e == {} ", JSONObject.toJSONString(e));
                    msg = e.getMessage();
                    e.printStackTrace();
                    isDeductMoney = false;
                }
                if (!isDeductMoney) {
                    throw new ServiceException(msg);
                }
                prizeOrder.setPayStatus(2);
                prizeOrder.setPayTime(new Date());
            }

            super.save(prizeOrder);

            //发放虚拟奖励
//            this.issueIncentives(result, prizeOrder);

            return ResultUtil.data(result);
        } catch (ServiceException e) {
            throw e;
        } finally {
            if (lock != null) {
                lock.unlock();
                log.info("prizeDraw 强制释放锁");
            }
        }
    }

    /**
     * 密码支付抽奖
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage<Object> passwordPaymentDraw() {
        Dictionary dictionary = dictionaryClient.getDict(Dictionary.builder().code(DictConstant.PRIZE_PRICE_NO).value(DictConstant.PRIZE_PRICE_01 + "").build());
        if (dictionary == null || StringUtils.isEmpty(dictionary.getId())) {
            throw new ServiceException("未获取到，抽奖所需f分，请联系管理员配置");
        }
        String sn = SnowFlake.createStr("P");
        //密码支付
        String money = dictionary.getValueName();
        int jzMoney = Integer.parseInt(dictionary.getValueName()) * 100;

        Long timestamp = System.currentTimeMillis();
        String callBack = apiProperties.getBuyer() + "/order/prize/app/callback";
        String username = Objects.requireNonNull(UserContext.getCurrentUser()).getUsername();
        String openId = Objects.requireNonNull(UserContext.getCurrentUser()).getOpenId();
        String str = String.format("appid=%s&paternerKey=%s&total_fee=%s&out_trade_no=%s&trade_type=%s&timestamp=%s&operation_type=%s&callback=%s&type=%s",
                appId, secret, jzMoney, sn, 2, timestamp, 3, null, "FMONEY");
        Digester sha1 = new Digester(DigestAlgorithm.SHA1);
        String sign = sha1.digestHex(MD5.create().digestHex(str).toLowerCase()).toLowerCase();
        String attach = "商城用户：" + username + "，转盘抽奖" + money;

        Map<String, Object> params = new HashMap<>();
        JSONObject paramsJson = new JSONObject();
        paramsJson.put("appid", appId);
        paramsJson.put("account", openId);
        paramsJson.put("total_fee", jzMoney);
        paramsJson.put("out_trade_no", sn);
        paramsJson.put("trade_type", 2);
        paramsJson.put("timestamp", timestamp);
        paramsJson.put("operation_type", 3);
        paramsJson.put("sign", sign);
        paramsJson.put("remark", attach);
        paramsJson.put("type", "FMONEY");
        paramsJson.put("version", "3");
        paramsJson.put("callback", null);
        params = paramsJson;
        //paramsJson.put("gmoney", gMoney);
//        return jsonObject;

        JSONObject jsonObject = payApi.createPayOrderV3(params);
        if (jsonObject.getInteger("code") != 200) {
            if (jsonObject.getInteger("code") == 10008) {
                throw new ServiceException(ResultCode.NAME_OUTH, jsonObject.getString("msg"));
            } else {
                throw new ServiceException(jsonObject.getString("msg"));
            }
        }
        //创建订单
        AuthUser currentUser = UserContext.getCurrentUser();
        PrizeOrder prizeOrder = PrizeOrder.builder()
                .userId(currentUser.getId())
                .memberName(currentUser.getUsername())
                .nickName(currentUser.getNickName())
                .price(BigDecimal.valueOf(Double.parseDouble(dictionary.getValueName())))
                .prizeStatus(1)
                .payStatus(1)
                .sn(sn)
                .build();
        super.save(prizeOrder);

        JSONObject result = new JSONObject();
        result.put("appid", appId);
        result.put("account", openId);
        result.put("total_fee", dictionary.getValueName());
        result.put("out_trade_no", sn);
        result.put("id", prizeOrder.getId());
        result.put("trade_type", 2);
        result.put("timestamp", timestamp);
        result.put("operation_type", 3);
        result.put("sign", sign);
        result.put("remark", attach);
        result.put("attach", "转盘抽奖");
        result.put("callback_url", callBack);
        result.put("type", "FMONEY");
        result.put("version", "3");
        return ResultUtil.data(result);
    }


    /**
     * 抽奖回调
     *
     * @return 抽奖回调
     */
    @Override
    public ResultMessage<Object> callback(PrizeOrder prizeOrder) {
        if (StringUtils.isEmpty(prizeOrder.getId())) {
            log.info("id为空 == {}", JSONObject.toJSONString(prizeOrder));
            return ResultUtil.error(500, "id为空");
        }
        log.info("Params == {}", JSONObject.toJSONString(prizeOrder));
        RLock lock = null;
        //锁后进行抽奖
        try {
            lock = redisson.getLock(LockPrefix.CALLBACK_PRIZE.getPrefix() + prizeOrder.getId());
            lock.lock(100, TimeUnit.SECONDS);
            //如果支付成功了，就直接返回了。防止重复提交
            PrizeOrder order = super.getById(prizeOrder.getId());
            if (order != null && order.getPrizeStatus().equals(2) && StringUtils.isNotEmpty(order.getPrizeId())) {
                PrizeGoods prizeGoods = prizeGoodsService.getById(order.getPrizeId());
                log.info("prizeGoods == {}", JSONObject.toJSONString(prizeGoods));
                return ResultUtil.data(prizeGoods);
            }

            //获取可参与抽奖的商品
            List<PrizeGoods> prizeGoodsList = this.prizeGoodsList();
            if (CollectionUtil.isEmpty(prizeGoodsList)) {
                throw new ServiceException("请先配置，抽奖奖品");
            }
            //抽奖
            PrizeGoods result = this.getLotteryItem(prizeGoodsList);

            //修改状态为支付状态
            prizeOrder.setPayStatus(2);
            prizeOrder.setPayTime(new Date());
            prizeOrder.setPrizeId(result.getId());
            prizeOrder.setPrizeName(result.getGoodsName());
            prizeOrder.setPrizeImg(result.getGoodsImage());
            prizeOrder.setPrizeType(result.getGoodsType());
            prizeOrder.setIsNeedToCollect(result.getIsNeedToCollect());
            super.updateById(prizeOrder);

            //发放虚拟奖励
//            this.issueIncentives(result, order);

            return ResultUtil.data(result);
        } catch (ServiceException e) {
            throw e;
        } finally {
            if (lock != null) {
                lock.unlock();
                log.info("callback 强制释放锁");
            }
        }
    }

    /**
     * 发放奖励 : 虚拟商品，直接发放到账户
     */
    private void issueIncentives(PrizeGoods result, PrizeOrder prizeOrder) {
        log.info("begin issueIncentives... result =={},  prizeOrder == {}", JSONObject.toJSONString(result), JSONObject.toJSONString(prizeOrder));
        //不是虚拟商品，直接返回
        if (!DictConstant.GOODS_TYPE_02.equals(result.getGoodsType())) {
            return;
        }
        User user = userClient.getById(prizeOrder.getUserId());
        log.info("prizeOrder.getUserId() == {}", prizeOrder.getUserId());
        if (user == null || StringUtils.isEmpty(user.getId())) {
            log.info("未获取到，用户，虚拟奖励不进行发放。result == {}, prizeOrder== {}", JSONObject.toJSONString(result), JSONObject.toJSONString(prizeOrder));
            return;
        }

        Dictionary build = Dictionary.builder().code(DictConstant.VIRTUAL_TYPE_NO).build();
        build.setValue(String.valueOf(result.getVirtualType()));
        Dictionary dictionary = dictionaryClient.getDict(build);
        //商城会员  20  到  29
        if (result.getVirtualType() != null && result.getVirtualType() >= 20 && result.getVirtualType() <= 29) {
            log.info("begin 充值商城会员");
            if (dictionary == null || StringUtils.isEmpty(dictionary.getId())) {
                log.error("未获取到商城会员字典 == {}", JSONObject.toJSONString(build));
                throw new ServiceException("未获取到商城会员字典");
            }
            int month = Integer.parseInt(dictionary.getDescription());
            LiVip liVip = vipClient.getByUserId(user.getId());
            boolean isVip = liVip != null && liVip.getEndTimeTow() != null && liVip.getEndTimeTow().getTime() > new Date().getTime();
            //还是会员 =》 在原有基础上 加xxx月
            if (isVip) {
                Date endTime = liVip.getEndTime();
                System.out.println("原始结束时间：" + endTime);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(endTime);
                calendar.add(Calendar.MONTH, month);
                Date newEndTime = calendar.getTime();
                System.out.println("增加月份后的结束时间：" + newEndTime);
                liVip.setEndTime(newEndTime);
                vipClient.update(liVip);
                log.info("end 充值商城会员1");
                return;
            }
            //已经会员过期。  没有创建会员（去创建会员）
            else {
                //没有创建会员，去创建会员
                //创建到期时间
                LocalDateTime currentDateTime = LocalDateTime.now();
                LocalDateTime nextMonthSameDayTime = currentDateTime.plusMonths(month);
                Date expireDate = Date.from(nextMonthSameDayTime.atZone(ZoneId.systemDefault()).toInstant());
                if (liVip == null) {
                    // 创建VIP会员记录
                    LiVip vip = LiVip.builder()
                            .userId(user.getId())
                            .vipStatus(VipStatusEnum.NORMAL.getStatus())
                            .openingMode(PayWayEnum.MANAGE_ADD.getValue())
                            .userName(user.getUsername())
                            .endTime(expireDate)
                            .phone(user.getMobile())
                            .build();
                    vip.setCreateBy(user.getId());
                    vip.setCreateTime(new Date());
                    boolean save = vipClient.save(vip);
                    log.info("end 充值商城会员2");
                    return;
                }
                // 更新会员记录
                liVip.setEndTime(expireDate);
                vipClient.update(liVip);
                log.info("end 充值商城会员3");
                return;
            }

        }
        //f分   30  到  39
        if (result.getVirtualType() != null && result.getVirtualType() >= 30 && result.getVirtualType() <= 39) {
            if (dictionary == null || StringUtils.isEmpty(dictionary.getId())) {
                log.error("未获取到f分字典 == {}", JSONObject.toJSONString(build));
                throw new ServiceException("未获取到f分字典");
            }

            //抽奖打款f分
            log.info("begin 抽奖打款f分");
            boolean orderReturn = payApi.payment(user.getOpenId(), "抽奖打款f分", (int) (Double.parseDouble(dictionary.getDescription()) * 100), 2, 3);
            log.info("end 抽奖打款f分=={}", orderReturn);
            if (!orderReturn) {
                throw new ServiceException("抽奖打款f分失败");
            }
            return;
        }
        //飞豆 ==>  此处字典值，对应的是，w_products表的id   40 ~  49
        if (result.getVirtualType() != null && result.getVirtualType() >= 40 && result.getVirtualType() <= 49) {
            if (dictionary == null || StringUtils.isEmpty(dictionary.getId())) {
                log.error("未获取到飞豆字典 == {}", JSONObject.toJSONString(build));
                throw new ServiceException("未获取到飞豆字典");
            }
            log.info("begin 飞豆打款");
            boolean b = payApi.paymentFeiDouToUser(user.getOpenId(), dictionary.getDescription());
            log.info("end 飞豆打款 = {}", b);
            return;
        }
    }

    /**
     * 获取商品列表
     */
    public List<PrizeGoods> prizeGoodsList() {
        // 获取购买次数：   获取今天的开始时间和结束时间
        LambdaQueryWrapper<PrizeOrder> countWhere = new LambdaQueryWrapper<>();
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime todayEnd = LocalDateTime.now();
        countWhere.between(PrizeOrder::getCreateTime, todayStart, todayEnd);
        countWhere.eq(PrizeOrder::getUserId, UserContext.getCurrentId());
        long count = super.count(countWhere);

        //获取可参与抽奖的商品
        LambdaQueryWrapper<PrizeGoods> prizeGoodsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        prizeGoodsLambdaQueryWrapper.eq(PrizeGoods::getPublishType, DictConstant.PUBLISH_TYPE_01);
        prizeGoodsLambdaQueryWrapper.le(PrizeGoods::getGoodsFrequency, count);
        return prizeGoodsService.list(prizeGoodsLambdaQueryWrapper);
    }

    /**
     * 抽奖
     *
     * @param prizeGoodsList 抽奖列表
     * @return 抽中商品
     */
    public PrizeGoods getLotteryItem(List<PrizeGoods> prizeGoodsList) {
        BigDecimal probabilitySum = BigDecimal.valueOf(0);
        for (PrizeGoods item : prizeGoodsList) {
            probabilitySum = probabilitySum.add(item.getProbability());
        }
        BigDecimal randomValue = BigDecimal.valueOf(new SecureRandom().nextDouble()).multiply(probabilitySum);
        BigDecimal currentProbability = BigDecimal.valueOf(0);
        for (PrizeGoods prizeGoods : prizeGoodsList) {
            currentProbability = currentProbability.add(prizeGoods.getProbability());
            if (randomValue.compareTo(currentProbability) < 0) {
                return prizeGoods;
            }
        }
        //如果随机值大于所有奖品的概率之和，返回null
        log.error("随机值大于所有奖品的概率之和，请检查配置 == {} ", JSONObject.toJSONString(prizeGoodsList));
        throw new ServiceException("随机值大于所有奖品的概率之和，请检查配置");
    }

    /**
     * 抽奖中奖记录
     */
    @Override
    public ResultMessage<Object> raffleWinningRecord(PageVO pageVO) {
        Page<PrizeOrder> resultPage = super.page(PageUtil.initPage(pageVO), this.createWrapper());
        return ResultUtil.data(this.conversion(resultPage));
    }

    private Page<PrizeOrder> conversion(Page<PrizeOrder> resultPage) {
        if (CollectionUtil.isEmpty(resultPage.getRecords())) {
            return resultPage;
        }
        List<String> goodsIdList = resultPage.getRecords().stream().map(PrizeOrder::getPrizeId).toList();
        List<PrizeGoods> prizeGoodsList = prizeGoodsService.listByIds(goodsIdList);
        if (CollectionUtil.isNotEmpty(prizeGoodsList)) {
            for (PrizeOrder prizeOrder : resultPage.getRecords()) {
                for (PrizeGoods prizeGoods : prizeGoodsList) {
                    if (prizeGoods.getId().equals(prizeOrder.getPrizeId())) {
                        prizeOrder.setPrizeImg(prizeGoods.getGoodsImage());
                        prizeOrder.setPrizeType(prizeGoods.getGoodsType());
                    }
                }
            }
        }
        return resultPage;
    }

    /*
     * 构建条件
     */
    private LambdaQueryWrapper<PrizeOrder> createWrapper() {
        LambdaQueryWrapper<PrizeOrder> prizeOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        prizeOrderLambdaQueryWrapper.eq(PrizeOrder::getUserId, UserContext.getCurrentId());
        prizeOrderLambdaQueryWrapper.eq(PrizeOrder::getPayStatus, 2);
        prizeOrderLambdaQueryWrapper.orderByDesc(PrizeOrder::getCreateTime);
        return prizeOrderLambdaQueryWrapper;
    }

    /**
     * 领取奖品
     */
    @Override
    public ResultMessage<Object> claimThePrize(PrizeOrder prizeOrder) {
        RLock lock = null;
        //锁后进行领奖
        try {
            lock = redisson.getLock(LockPrefix.CALLBACK_PRIZE.getPrefix() + prizeOrder.getId());
            lock.lock(100, TimeUnit.SECONDS);
            log.info("prizeOrder == {}", JSONObject.toJSONString(prizeOrder));
            //参数校验
            PrizeOrder updateOrder = this.claimThePrizeCheck(prizeOrder);
            updateOrder.setPrizeStatus(2);
            updateOrder.setPrizeTime(new Date());
            return ResultUtil.data(super.updateById(updateOrder));
        } catch (Exception e) {
            throw e;
        } finally {
            if (lock != null) {
                lock.unlock();
                log.info("callback 强制释放锁");
            }
        }
    }

    private PrizeOrder claimThePrizeCheck(PrizeOrder prizeOrder) {
        if (StringUtils.isEmpty(prizeOrder.getId())) {
            throw new ServiceException("id为空");
        }
//        if (StringUtils.isEmpty(prizeOrder.getConsigneeAddressIdPath())) {
//            throw new ServiceException("收货地址id：consigneeAddressIdPath为空");
//        }
//        if (StringUtils.isEmpty(prizeOrder.getConsigneeAddressPath())) {
//            throw new ServiceException("收货地址名称：consigneeAddressPath为空");
//        }
        PrizeOrder order = super.getById(prizeOrder.getId());
        if (order == null) {
            log.info("未获取到订单信息 === {}", prizeOrder.getId());
            throw new ServiceException("未获取到订单信息");
        }
        //是虚拟商品的时候，不校验收货地址。去领取虚拟奖励
        if (StringUtils.isNotEmpty(order.getPrizeId())) {
            PrizeGoods prizeGoods = prizeGoodsService.getById(order.getPrizeId());
            if (prizeGoods == null) {
                throw new ServiceException("待领取奖品，已被删除，请联系客服");
            }
            //是虚拟商品
            if (DictConstant.GOODS_TYPE_02.equals(prizeGoods.getGoodsType())) {
                //待领取状态，且需要领取
                if (DictConstant.PRIZE_STATUS_01.equals(order.getPrizeStatus()) && DictConstant.IS_NEED_TO_COLLECT_1.equals(order.getIsNeedToCollect())) {
                    //奖励发放
                    issueIncentives(prizeGoods, order);
                }
                return order;
            }
        }
        if (StringUtils.isEmpty(prizeOrder.getConsigneeDetail())) {
            throw new ServiceException("收货详情地址：consigneeDetail为空");
        }
        if (StringUtils.isEmpty(prizeOrder.getConsigneeMobile())) {
            throw new ServiceException("收货人手机号：consigneeMobile为空");
        }
        if (StringUtils.isEmpty(prizeOrder.getConsigneeName())) {
            throw new ServiceException("收货人昵称：consigneeName为空");
        }
        return prizeOrder;
    }


    /**
     * 查看物流信息
     *
     * @param id 订单ID
     */
    @Override
    public ResultMessage<Object> viewLogisticsInformation(String id) {
        ViewLogisticVO result = new ViewLogisticVO();
        PrizeOrder order = super.getById(id);
        if (order == null) {
            throw new ServiceException("未获取到订单信息");
        }
        result.setGrowAwardStatus(order);
        result.setTraces(new Traces());
        if (StringUtils.isNotEmpty(order.getExpressId()) && StringUtils.isNotEmpty(order.getExpressNo()) && StringUtils.isNotEmpty(order.getConsigneeMobile())) {
            Traces traces = logisticsClient.getLogistic(order.getExpressId(), order.getExpressNo(), order.getConsigneeMobile().substring(order.getConsigneeMobile().length() - 4));
            result.setTraces(Objects.requireNonNullElseGet(traces, Traces::new));
        }
        return ResultUtil.data(result);
    }


    /**
     * 获取最近一次 订单收货地址
     * @return 获取最近一次 订单收货地址
     */
    @Override
    public ResultMessage<Object> getHistoricalAddress() {
        PrizeOrder result = new PrizeOrder();
        LambdaQueryWrapper<PrizeOrder> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(PrizeOrder::getUserId, UserContext.getCurrentId());
        orderLambdaQueryWrapper.isNotNull(PrizeOrder::getConsigneeMobile);
        orderLambdaQueryWrapper.isNotNull(PrizeOrder::getConsigneeName);
        orderLambdaQueryWrapper.isNotNull(PrizeOrder::getConsigneeDetail);
        orderLambdaQueryWrapper.orderByDesc(PrizeOrder::getPrizeTime);
        orderLambdaQueryWrapper.last("limit 1");
        PrizeOrder prizeOrder = super.getOne(orderLambdaQueryWrapper);
        if (prizeOrder != null) {
            result.setConsigneeName(prizeOrder.getConsigneeName());
            result.setConsigneeMobile(prizeOrder.getConsigneeMobile());
            result.setConsigneeDetail(prizeOrder.getConsigneeDetail());
        }
        return ResultUtil.data(result);
    }

    /**
     * 查询抽奖记录
     *
     * @param dto
     * @return
     */
    @Override
    public Page<PrizeOrder> getPrizeOrderList(PrizeOrderDTO dto) {
        //默认查询7天数据
        if (dto.getStartTime() == null || dto.getEndTime() == null) {
            LocalDateTime today = LocalDateTime.now();
            //7天前的日期
            dto.setStartTime(today.minusDays(8));
            dto.setEndTime(today.with(LocalTime.MAX));
        }
        Page<PrizeOrder> page = baseMapper.selectPage(new Page<>(dto.getPageNumber(), dto.getPageSize()), dto.toQueryWrapper());
        if (CollUtil.isNotEmpty(page.getRecords())) {
            page.getRecords().stream().forEach(e -> {
                if (StringUtils.isNotEmpty(e.getConsigneeAddressPath()) && StringUtils.isNotEmpty(e.getConsigneeDetail())) {
                    e.setConsigneeDetail(e.getConsigneeAddressPath().join(e.getConsigneeDetail()));
                }
            });
        }
        return page;
    }

    /**
     * 导出订单
     * @param dto
     * @return
     */
    @Override
    public List<PrizeOrder> export(PrizeOrderDTO dto) {
        if (dto.getStartTime() == null || dto.getEndTime() == null) {
            LocalDateTime today = LocalDateTime.now();
            //7天前的日期
            dto.setStartTime(today.minusDays(8));
            dto.setEndTime(today.with(LocalTime.MAX));
        }

        return this.conversionExport(baseMapper.selectList(dto.toQueryWrapper()));
    }

    private List<PrizeOrder> conversionExport(List<PrizeOrder> prizeOrders) {
        if (CollectionUtil.isEmpty(prizeOrders)) {
            return new ArrayList<>();
        }
        for (PrizeOrder prizeOrder : prizeOrders) {
            if (DictConstant.PRIZE_STATUS_01.equals(prizeOrder.getPrizeStatus())) {
                prizeOrder.setPrizeStatusName("待领取");
            }
            if (DictConstant.PRIZE_STATUS_02.equals(prizeOrder.getPrizeStatus())) {
                prizeOrder.setPrizeStatusName("已领取");
            }
            if (OrderConstant.PRIZE_TYPE_01.equals(prizeOrder.getPrizeType())) {
                prizeOrder.setPrizeTypeName("实物商品");
            }
            if (OrderConstant.PRIZE_TYPE_02.equals(prizeOrder.getPrizeType())) {
                prizeOrder.setPrizeTypeName("虚拟商品");
            }
            if (OrderConstant.PAY_STATUS_01.equals(prizeOrder.getPayStatus())) {
                prizeOrder.setPayStatusName("未支付");
            }
            if (OrderConstant.PAY_STATUS_02.equals(prizeOrder.getPayStatus())) {
                prizeOrder.setPayStatusName("已支付");
            }
            if (DictConstant.IS_NEED_TO_COLLECT_1.equals(prizeOrder.getIsNeedToCollect())) {
                prizeOrder.setIsNeedToCollectName("需要");
            }
            if (DictConstant.IS_NEED_TO_COLLECT_2.equals(prizeOrder.getIsNeedToCollect())) {
                prizeOrder.setIsNeedToCollectName("不需要");
            }
        }
        return prizeOrders;
    }

    /**
     * 填写物流信息
     *
     * @param order
     * @return
     */
    @Override
    public ResultMessage<Object> inputExpressInfo(PrizeOrder order) {
        if (StrUtil.isBlank(order.getId())) {
            return ResultUtil.error(400, "抽奖记录id不可为空");
        }
        if (StrUtil.isBlank(order.getExpressId())) {
            return ResultUtil.error(400, "请选择物流公司");
        }
        if (StrUtil.isBlank(order.getExpressNo())) {
            return ResultUtil.error(400, "请填写物流单号");
        }
        int result = baseMapper.updateById(order);
        return result > 0 ? ResultUtil.success() : ResultUtil.error();
    }

    /**
     * 抽奖金额统计
     *
     * @param dto
     * @return
     */
    @Override
    public PrizeOrderStatisticsVO prizePriceStatistics(PrizeOrderDTO dto) {
        //默认查询7天数据
        if (dto.getStartTime() == null || dto.getEndTime() == null) {
            LocalDateTime today = LocalDateTime.now();
            //7天前的日期
            dto.setStartTime(today.minusDays(8));
            dto.setEndTime(today.with(LocalTime.MAX));
        }
        PrizeOrderStatisticsVO vo = baseMapper.prizePriceStatistics(dto);
        //人数
        PrizeOrderStatisticsVO vo1 = baseMapper.prizeUserCountStatistics(dto);
        //f分
        PrizeOrderStatisticsVO vo2 = baseMapper.prizeFScoreStatistics(dto);
        //飞豆
        PrizeOrderStatisticsVO vo3 = baseMapper.prizeWingedBeanStatistics(dto);

        vo.setUserCountStaticstics(vo1.getUserCountStaticstics());
        vo.setFScore(vo2.getFScore());
        vo.setWingedBean(vo3.getWingedBean());
        return vo;
    }

    /**
     * 抽奖用户数量统计 已弃用
     *
     * @param dto
     * @return
     */
    @Override
    public PrizeOrderStatisticsVO prizeUserCountStatistics(PrizeOrderDTO dto) {
        return baseMapper.prizeUserCountStatistics(dto);
    }
}